/*
 * 版权所有 (C) 2015 知启蒙(ZHIQIM) 保留所有权利。[遇见知启蒙，邂逅框架梦]
 * 
 * https://zhiqim.org/project/zhiqim_framework/zhiqim_kernel.htm
 *
 * Zhiqim Kernel is licensed under Mulan PSL v2.
 * You can use this software according to the terms and conditions of the Mulan PSL v2.
 * You may obtain a copy of Mulan PSL v2 at:
 *          http://license.coscl.org.cn/MulanPSL2
 * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
 * EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
 * MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
 * See the Mulan PSL v2 for more details.
 */
package org.zhiqim.kernel.util;

import java.lang.reflect.Field;
import java.lang.reflect.Modifier;

import org.zhiqim.kernel.annotation.AnAlias;
import org.zhiqim.kernel.constants.SignConstants;

/**
 * 对象相关工具类
 * 
 * @version v1.0.0 @author zouzhigang 2014-2-27 新建与整理
 */
@AnAlias("Objects")
public class Objects implements SignConstants
{
    /**************************************************************/
    //拷贝属性方法
    /**************************************************************/
    
    /** 浅拷贝属性,静态和临时两种属性不拷贝,父类的属性不拷贝 */
    public static <T> T copy(Object src, T dst)
    {
        Asserts.notNull(src, _SRC_);
        Asserts.notNull(dst, _DST_);
        
        copyFields(src, dst, src.getClass(), dst.getClass());
        return dst;
    }
    
    /** 对源和目标对象进行深度拷贝,静态和临时两种属性不拷贝 */
    public static <T> T copyDeep(Object src, T dst)
    {
        Asserts.notNull(src, _SRC_);
        Asserts.notNull(dst, _DST_);
        
        Class<?> superSrcClass = src.getClass();
        while (superSrcClass != null && superSrcClass != Object.class)
        {
            Class<?> superDestClass = dst.getClass();
            while (superDestClass != null && superDestClass != Object.class)
            {
                copyFields(src, dst, superSrcClass, superDestClass);
                superDestClass = superDestClass.getSuperclass();
            }
            
            superSrcClass = superSrcClass.getSuperclass();
        }
        return dst;
    }
    
    /** 根据原类深属性拷贝(父类的循环查找拷贝),静态和临时两种属性不拷贝 */
    public static <T> T copySrcDeep(Object src, T dst)
    {
        Asserts.notNull(src, _SRC_);
        Asserts.notNull(dst, _DST_);
        
        copyFields(src, dst, src.getClass(), dst.getClass());
        Class<?> superSrcClass = src.getClass().getSuperclass();
        while (superSrcClass != null && superSrcClass != Object.class)
        {
            copyFields(src, dst, superSrcClass, dst.getClass());
            
            superSrcClass = superSrcClass.getSuperclass();
        }
        return dst;
    }
    
    /** 根据目标类深属性拷贝(父类的循环查找拷贝),静态和临时两种属性不拷贝 */
    public static <T> T copyDstDeep(Object src, T dst)
    {
        Asserts.notNull(src, _SRC_);
        Asserts.notNull(dst, _DST_);
        
        copyFields(src, dst, src.getClass(), dst.getClass());
        Class<?> superDestClass = dst.getClass().getSuperclass();
        while (superDestClass != null && superDestClass != Object.class)
        {
            copyFields(src, dst, src.getClass(), superDestClass);
            
            superDestClass = superDestClass.getSuperclass();
        }
        return dst;
    }
    
    /** 当前对象内属性拷贝,静态和临时两种属性不拷贝 */
    private static void copyFields(Object src, Object dst, Class<?> sClass, Class<?> dClass)
    {
        try
        {
            Field[] sFields = sClass.getDeclaredFields();
            Field[] dFields = dClass.getDeclaredFields();
            for (int i=0;i<dFields.length;i++)
            {
                Field dField = dFields[i];
                int mod = dField.getModifiers();
                if (Modifier.isStatic(mod) || Modifier.isTransient(mod))
                    continue;//静态和临时两种属性不拷贝
                
                for (int j=0;j<sFields.length;j++)
                {
                    Field sField = sFields[j];
                    int modj = sField.getModifiers();
                    if (Modifier.isStatic(modj) || Modifier.isTransient(modj))
                        continue;
                    
                    if (dField.getName().equals(sField.getName()))
                    {
                        sField.setAccessible(true);
                        Object value = sField.get(src);
                        dField.setAccessible(true);
                        dField.set(dst, value);
                        break;
                    }
                }
            }
        }
        catch(Exception e)
        {
            e.printStackTrace();
            //异常不处理
        }
    }
    
}
